package com.qd.pandaparkflow.compment.park;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.math.Money;
import com.qd.pandaparkflow.context.PriceContext;
import com.qd.pandaparkflow.dto.PerViewDTO;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Optional;

/**
 * 按次计费
 * 夜间（0点至8点），每次5元
 *
 * @author sjk
 */
@ConditionalOnProperty(prefix = "liteflow", name = "enable", havingValue = "true")
@LiteflowComponent(value = "perViewCmp")
@Slf4j
public class PerViewComponent extends NodeComponent {

    @Override
    public void process() throws Exception {
        final PriceContext priceContext = this.getContextBean(PriceContext.class);
        final PerViewDTO perView = priceContext.getPerView();
        if (null == perView) {
            return;
        }
        final LocalDateTime start = priceContext.getStartTime();
        final LocalDateTime end = priceContext.getEndTime();
        final LocalTime startTime = perView.getStartTime();
        final LocalTime endTime = perView.getEndTime();
        Money allOrderPrice = new Money(Optional.ofNullable(priceContext.getFinalOrderPrice()).orElse(new BigDecimal(0L)));
        Money orderPrice = new Money(0L);

        StringBuilder logBuilder = new StringBuilder();
        logBuilder.append("按次计费，计费时段[")
                .append(startTime.toString()).append("-").append(endTime.toString()).append("]")
                .append(",开始时间[").append(start.toString()).append("],结束时间[").append(end.toString()).append("]");
        final int count = count(startTime, endTime, start, end);
        if (count > 0) {
            orderPrice = orderPrice.add(new Money(perView.getUnitPrice())).divide(new BigDecimal(count), RoundingMode.HALF_UP);
            allOrderPrice = allOrderPrice.add(orderPrice);
            priceContext.setFinalOrderPrice(allOrderPrice.getAmount());
        }
        logBuilder.append(",次数[").append(count).append("]")
                .append(",当前金额[").append(orderPrice.getAmount().toPlainString()).append("],总金额[").append(allOrderPrice.getAmount().toPlainString()).append("]");
        priceContext.getPrintLog().add(logBuilder.toString());
    }

    /**
     * 计算次数
     *
     * @param startTime 计费开始时段
     * @param endTime   计费结束时段
     * @param start     停车开始时间
     * @param end       停车结束时间
     * @return 满足条件的次数
     */
    public int count(LocalTime startTime, LocalTime endTime, LocalDateTime start, LocalDateTime end) {
        int count = 0;
        final Duration duration = LocalDateTimeUtil.between(start, end);
        long days = duration.toDays();
        if (duration.toHours() > 0) {
            days += 1;
        }
        //相差的天数
        for (int i = 0; i < days; i++) {
            LocalDateTime s = start;
            LocalDateTime e = end;
            LocalDate localDate = start.toLocalDate();
            if (i == 0) {
                //第一天的结束时间
                e = LocalDateTime.of(localDate.getYear(), localDate.getMonth(), localDate.getDayOfMonth(), 23, 59, 59);
            }
            if (i > 0) {
                localDate = localDate.plusDays(1);
                s = LocalDateTime.of(localDate.getYear(), localDate.getMonth(), localDate.getDayOfMonth(), 0, 0, 0);
            }
            if (s.isBefore(start)) {
                s = start;
            }
            if (e.isAfter(end)) {
                e = end;
            }
            //拼装当天的开始时间和结束时间
            LocalDateTime startLocalDateTime = LocalDateTime.of(localDate.getYear(), localDate.getMonth(), localDate.getDayOfMonth(), startTime.getHour(), startTime.getMinute(), startTime.getSecond());
            LocalDateTime endLocalDateTime = LocalDateTime.of(localDate.getYear(), localDate.getMonth(), localDate.getDayOfMonth(), endTime.getHour(), endTime.getMinute(), endTime.getSecond());
            endLocalDateTime = endLocalDateTime.isAfter(e) ? e : endLocalDateTime;

            if (LocalDateTimeUtil.isOverlap(startLocalDateTime, endLocalDateTime, s, e)) {
                count++;
            }
        }
        return count;
    }
}